function mxTooltipHandler(graph, delay)
{
	if (graph != null)
	{
		this.graph = graph;
		this.delay = delay || 500;

		if (document.body != null)
		{
			this.graph.addMouseListener(this);
		}
	}
};
mxTooltipHandler.prototype.zIndex = 10005;
mxTooltipHandler.prototype.graph = null;
mxTooltipHandler.prototype.delay = null;
mxTooltipHandler.prototype.hideOnHover = false;
mxTooltipHandler.prototype.enabled = true;
mxTooltipHandler.prototype.isEnabled = function()
{
	return this.enabled;
};
mxTooltipHandler.prototype.setEnabled = function(enabled)
{
	this.enabled = enabled;
};
mxTooltipHandler.prototype.isHideOnHover = function()
{
	return this.hideOnHover;
};
mxTooltipHandler.prototype.setHideOnHover = function(value)
{
	this.hideOnHover = value;
};
mxTooltipHandler.prototype.init = function()
{
	if (document.body != null)
	{
		this.div = document.createElement('div');
		this.div.className = 'mxTooltip';
		this.div.style.visibility = 'hidden';
		this.div.style.zIndex = this.zIndex;

		if (!mxClient.IS_IE && mxClient.TOOLTIP_SHADOWS)
		{
			this.shadow = document.createElement('div');
			this.shadow.className = 'mxTooltipShadow';
			this.shadow.style.visibility = 'hidden';
			this.shadow.style.zIndex = this.zIndex;
			mxUtils.setOpacity(this.shadow, 70);
			document.body.appendChild(this.shadow);
		}
		else if (mxClient.IS_IE && !mxClient.TOOLTIP_SHADOWS)
		{
			this.div.style.filter = '';
		}
		document.body.appendChild(this.div);
		var self = this;
		mxEvent.addListener(this.div, 'mousedown', function(evt)
		{
			self.hide();
		});
	}
};
mxTooltipHandler.prototype.mouseDown = function(sender, me)
{
	this.reset(me, false);
	this.hide();
};
mxTooltipHandler.prototype.mouseMove = function(sender, me)
{
	if (me.getX() != this.lastX || me.getY() != this.lastY)
	{
		this.reset(me, true);

		if (this.isHideOnHover() || me.getCell() != this.cell || me.getHandle() != this.index)
		{
			this.hide();
		}
	}
	this.lastX = me.getX();
	this.lastY = me.getY();
};
mxTooltipHandler.prototype.mouseUp = function(sender, me)
{
	this.reset(me, true);
	this.hide();
};
mxTooltipHandler.prototype.reset = function(me, restart)
{
	if (this.thread != null)
	{
		window.clearTimeout(this.thread);
		this.thread = null;
	}

	if (restart && this.isEnabled() && me.getState() != null && this.div.style.visibility == 'hidden')
	{
		var x = me.getX();
		var y = me.getY();
		var self = this;
		this.thread = window.setTimeout(function()
		{
			if (!self.graph.isEditing() && !self.graph.panningHandler.isMenuShowing())
			{
				var tip = self.graph.getTooltipForEvent(me);
				self.show(tip, x, y);
				self.cell = me.getCell();
				self.index = me.getHandle();
			}
		}, this.delay);
	}
};
mxTooltipHandler.prototype.hide = function()
{
	if (this.shadow != null)
	{
		this.shadow.style.visibility = 'hidden';
	}

	if (this.div != null)
	{
		this.div.style.visibility = 'hidden';
	}
};
mxTooltipHandler.prototype.show = function(tip, x, y)
{
	if (tip != null && tip.length > 0)
	{
		var origin = mxUtils.getScrollOrigin();
		this.div.style.left = (x + origin.x) + 'px';
		this.div.style.top = (y + mxConstants.TOOLTIP_VERTICAL_OFFSET + origin.y) + 'px';

		if (!mxUtils.isNode(tip))
		{
			this.div.innerHTML = tip.replace(/\n/g, '<br>');
		}
		else
		{
			this.div.innerHTML = '';
			this.div.appendChild(tip);
		}
		this.div.style.visibility = '';
		mxUtils.fit(this.div);

		if (this.shadow != null)
		{
			this.shadow.style.width = this.div.offsetWidth + 'px';
			this.shadow.style.height = this.div.offsetHeight + 'px';
			this.shadow.style.left = (parseInt(this.div.style.left) + 3) + 'px';
			this.shadow.style.top = (parseInt(this.div.style.top) + 3) + 'px';
			this.shadow.style.visibility = '';
		}
	}
};
mxTooltipHandler.prototype.destroy = function()
{
	this.graph.removeMouseListener(this);
	mxEvent.release(this.div);

	if (this.div != null && this.div.parentNode != null)
	{
		this.div.parentNode.removeChild(this.div);
	}
	this.div = null;

	if (this.shadow != null)
	{
		mxEvent.release(this.shadow);

		if (this.shadow.parentNode != null)
		{
			this.shadow.parentNode.removeChild(this.shadow);
		}
		this.shadow = null;
	}
};